﻿using Quartz;
using Raffles.OA.Data;
using Raffles.OA.Utility;
using SqlSugar;
using System;
using System.Collections.Generic;

namespace Raffles.OA.Job
{
    public class JobCenter
    {
        private static SqlSugarScope _dbContext = ReportDB.Db;
        public void Start()
        {
            List<AutoJob> jobs = _dbContext.Queryable<AutoJob>().ToList();
            AddScheduleJob(jobs);
        }

        #region 添加任务计划
        /// <summary>
        /// 添加任务计划
        /// </summary>
        /// <returns></returns>
        private void AddScheduleJob(List<AutoJob> entityList)
        {
            try
            {
                foreach (AutoJob entity in entityList)
                {
                    if (entity.StartTime == null)
                    {
                        entity.StartTime = DateTime.Now;
                    }
                    DateTimeOffset starRunTime = DateBuilder.NextGivenSecondDate(entity.StartTime, 1);
                    if (entity.EndTime == null)
                    {
                        entity.EndTime = DateTime.MaxValue.AddDays(-1);
                    }
                    DateTimeOffset endRunTime = DateBuilder.NextGivenSecondDate(entity.EndTime, 1);

                    var scheduler =  JobScheduler.GetScheduler();
                    IJobDetail job = JobBuilder.Create<JobExecute>().WithIdentity(entity.JobName, entity.JobGroupName).Build();
                    job.JobDataMap.Add("Id", entity.Id);

                    ICronTrigger trigger = (ICronTrigger)TriggerBuilder.Create()
                                                 .StartAt(starRunTime)
                                                 .EndAt(endRunTime)
                                                 .WithIdentity(entity.JobName, entity.JobGroupName)
                                                 .WithCronSchedule(entity.CronExpression)
                                                 .Build();

                    scheduler.ScheduleJob(job, trigger);
                    scheduler.Start();
                }
            }
            catch (Exception ex)
            {
                NLogHelper.Error(ex.Message);
            }
        }
        #endregion

        #region 清除任务计划
        /// <summary>
        /// 清除任务计划
        /// </summary>
        /// <returns></returns>
        public void ClearScheduleJob()
        {
            try
            {
                JobScheduler.GetScheduler().Clear();
            }
            catch (Exception ex)
            {
                NLogHelper.Error(ex.Message);
            }
        }
        #endregion

        #region 重置调度时间
        /// <summary>
        /// 重置调度时间
        /// </summary>
        /// <param name="triggerName"></param>
        /// <param name="groupName"></param>
        /// <param name="cron"></param>
        /// <returns></returns>
        public void ModifyScheduleJob(AutoJob entity)
        {
            TriggerKey triggerKey = new TriggerKey(entity.JobName, entity.JobGroupName);  
            var scheduler = JobScheduler.GetScheduler();
            if ((scheduler.GetTrigger(triggerKey) is ICronTrigger trigger))
            {  
                if (entity.StartTime == null)
                {
                    entity.StartTime = DateTime.Now;
                }
                DateTimeOffset starRunTime = DateBuilder.NextGivenSecondDate(entity.StartTime, 1);
                if (entity.EndTime == null)
                {
                    entity.EndTime = DateTime.MaxValue.AddDays(-1);
                }
                DateTimeOffset endRunTime = DateBuilder.NextGivenSecondDate(entity.EndTime, 1);
                //WithMisfireHandlingInstructionDoNothing
                //——不触发立即执行
                //——等待下次Cron触发频率到达时刻开始按照Cron频率依次执行

                //withMisfireHandlingInstructionIgnoreMisfires
                //——以错过的第一个频率时间立刻开始执行
                //——重做错过的所有频率周期后
                //——当下一次触发频率发生时间大于当前时间后，再按照正常的Cron频率依次执行

                //withMisfireHandlingInstructionFireAndProceed
                //——以当前时间为触发频率立刻触发一次执行
                //——然后按照Cron频率依次执行
                ICronTrigger updateTrigger = (ICronTrigger)TriggerBuilder.Create()
                                                .StartAt(starRunTime)
                                                .EndAt(endRunTime)
                                                .WithIdentity(entity.JobName, entity.JobGroupName)
                                                .WithCronSchedule(entity.CronExpression,x=>x.WithMisfireHandlingInstructionDoNothing())
                                                .Build();
                scheduler.RescheduleJob(triggerKey, updateTrigger);
            }
            else
            {
                if (entity.StartTime == null)
                {
                    entity.StartTime = DateTime.Now;
                }
                DateTimeOffset starRunTime = DateBuilder.NextGivenSecondDate(entity.StartTime, 1);
                if (entity.EndTime == null)
                {
                    entity.EndTime = DateTime.MaxValue.AddDays(-1);
                }
                DateTimeOffset endRunTime = DateBuilder.NextGivenSecondDate(entity.EndTime, 1); 
                IJobDetail job = JobBuilder.Create<JobExecute>().WithIdentity(entity.JobName, entity.JobGroupName).Build();
                job.JobDataMap.Add("Id", entity.Id);

                ICronTrigger newTrigger = (ICronTrigger)TriggerBuilder.Create()
                                             .StartAt(starRunTime)
                                             .EndAt(endRunTime)
                                             .WithIdentity(entity.JobName, entity.JobGroupName)
                                             .WithCronSchedule(entity.CronExpression, x => x.WithMisfireHandlingInstructionDoNothing())
                                             .Build();

                scheduler.ScheduleJob(job, newTrigger);
            }
        }
        #endregion
    }
}
